/*  PCSX2 - PS2 Emulator for PCs
 *  Copyright (C) 2002-2010  PCSX2 Dev Team
 *
 *  PCSX2 is free software: you can redistribute it and/or modify it under the terms
 *  of the GNU Lesser General Public License as published by the Free Software Found-
 *  ation, either version 3 of the License, or (at your option) any later version.
 *
 *  PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 *  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 *  PURPOSE.  See the GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along with PCSX2.
 *  If not, see <http://www.gnu.org/licenses/>.
 */

#include "PrecompiledHeader.h"

#include "Config.h"

#include "App.h"
#include "AppConfig.h"
#include "AppSaveStates.h"
#include "AppGameDatabase.h"
#include "ConfigurationPanels.h"
#include "CDVD/IsoFileFormats.h"
#include "CDVD/CDVDaccess.h"

#include "Utilities/IniInterface.h"
#include "Dialogs/ConfigurationDialog.h"

#include <wx/dir.h>
#include <wx/generic/progdlgg.h>
#include <wx/spinctrl.h>

#include <wx/filepicker.h>

using namespace pxSizerFlags;

Dialogs::CreateGameSettings::CreateGameSettings( wxWindow* parent ) 
: BaseApplicableDialog( parent, AddAppName(_("Create Game Settings")) )
{
	wxBoxSizer& s_buttons( *new wxBoxSizer(wxHORIZONTAL) );

	s_buttons += new wxButton( this, wxID_CANCEL )			| pxProportion(2);
	s_buttons += pxStretchSpacer(3);

	wxButton* Create = new wxButton( this, wxID_OK, _("Create") );
	s_buttons += Create | pxProportion(2);
	wxString label = wxEmptyString;

	wxFile fp;
	ConfigGame* IniSettingsFolder = new ConfigGame( DiscSerial, ElfCRC );

	if(ElfCRC == 0 && DiscSerial == wxEmptyString)
	{
		label.Printf(L"Please, boot game...");
		Create->Disable();
	}
	else if( fp.Access(IniSettingsFolder->GetIniFolder() + L"Base.ini", fp.read) )
	{
		label.Printf(L"Settings for " + IniSettingsFolder->GetGameId() + L" found on disk. Change it?");

		Create->SetLabel(L"Change");
		Create->Enable();
	}
	else
	{
		label.Printf(L"Create settings for " + IniSettingsFolder->GetGameId() + L"?");

		Create->Enable();
	}

	wxBoxSizer& s_panel( *new wxBoxSizer(wxVERTICAL) );

	s_panel += Label(label) | StdCenter();
	s_panel += 8;
	s_panel += s_buttons    | StdCenter();

	*this += s_panel | StdExpand();

	Connect( wxID_OK, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CreateGameSettings::OnOk_Click ) );
}

void Dialogs::CreateGameSettings::OnOk_Click( wxCommandEvent& evt )
{
	this->Hide();
	ConfigGameDialog(this).ShowModal();
	EndModal( wxID_OK );
}

ConfigGame::ConfigGame() {}
ConfigGame::ConfigGame(wxString Serial, u32 CRC):m_Serial(Serial),m_CRC(CRC){}

void ConfigGame::ConvertPluginFilenames( wxString (&passins), const PluginsEnum_t& pid )
{
	passins = wxGetApp().Overrides.Filenames[pid].GetFullPath();

	if( passins.IsEmpty() || !wxFileExists( passins[pid] ) )
		passins = g_Conf->FullpathTo( pid );
}

void ConfigGame::ConfigurePlugin(const PluginsEnum_t& pid)
{
	wxDoNotLogInThisScope please;

	wxString passins;
	ConvertPluginFilenames( passins, pid );
	CorePlugins.SendSettingsFolder( pid, GetIniFolder() );
	CorePlugins.Configure(pid);
	pxYield(5);
	CorePlugins.SendSettingsFolder();
}

uint ConfigGame::SetConf(IniInterface& ini, const wxString& var, uint reg)
{
	static int i = 0;
	if(ini.IsSaving())i = reg;
	ini.Entry(var, i);
	return i;
}

wxString ConfigGame::SetConf(IniInterface& ini, const wxString& var, wxString reg)
{
	ini.Entry(var, reg);
	return reg;
}

bool ConfigGame::SetConf(IniInterface& ini, const wxString& var, bool reg)
{
	static int i = 0;
	if(ini.IsSaving())i = reg;
	ini.Entry(var, i);
	return !!i;
}

u8 ConfigGame::SetConf(IniInterface& ini, const wxString& var, u8 reg)
{
	return (u8)SetConf(ini, var, (uint) reg);
}

void ConfigGame::Conf(IniInterface& ini)
{
	ini.Entry(L"GS_FramerateNTSC",	dest.GS.FramerateNTSC	);
	ini.Entry(L"GS_FrameratePAL",	dest.GS.FrameratePAL	);

	uint i = 0;

	dest.Speedhacks.VUCycleSteal		= SetConf(ini, L"Speedhacks_VUCycleSteal",	dest.Speedhacks.VUCycleSteal);
	dest.Speedhacks.EECycleRate			= SetConf(ini, L"Speedhacks_EECycleRate",	dest.Speedhacks.EECycleRate);
	dest.Speedhacks.IOPCycleSteal		= SetConf(ini, L"Speedhacks_IOPCycleSteal",	dest.Speedhacks.IOPCycleSteal);
	dest.Speedhacks.eeBranchHack		= SetConf(ini, L"Speedhacks_eeBranchHack",	dest.Speedhacks.eeBranchHack);
	dest.Speedhacks.fastCDVD			= SetConf(ini, L"Speedhacks_fastCDVD",		dest.Speedhacks.fastCDVD);
	dest.Speedhacks.IntcStat			= SetConf(ini, L"Speedhacks_IntcStat",		dest.Speedhacks.IntcStat);
	dest.Speedhacks.vuBlockHack			= SetConf(ini, L"Speedhacks_vuBlockHack",	dest.Speedhacks.vuBlockHack);
	dest.Speedhacks.vuFlagHack			= SetConf(ini, L"Speedhacks_vuFlagHack",	dest.Speedhacks.vuFlagHack);
	dest.Speedhacks.vuMinMax			= SetConf(ini, L"Speedhacks_vuMinMax",		dest.Speedhacks.vuMinMax);
	dest.Speedhacks.WaitLoop			= SetConf(ini, L"Speedhacks_WaitLoop",		dest.Speedhacks.WaitLoop);

	dest.Gamefixes.EETimingHack			= SetConf(ini, L"Gamefixes_EETimingHack",	dest.Gamefixes.EETimingHack);
	dest.Gamefixes.FpuCompareHack		= SetConf(ini, L"Gamefixes_FpuCompareHack",	dest.Gamefixes.FpuCompareHack);
	dest.Gamefixes.FpuMulHack			= SetConf(ini, L"Gamefixes_FpuMulHack",		dest.Gamefixes.FpuMulHack);
	dest.Gamefixes.FpuNegDivHack		= SetConf(ini, L"Gamefixes_FpuNegDivHack",	dest.Gamefixes.FpuNegDivHack);
	dest.Gamefixes.IPUWaitHack			= SetConf(ini, L"Gamefixes_IPUWaitHack",	dest.Gamefixes.IPUWaitHack);
	dest.Gamefixes.OPHFlagHack			= SetConf(ini, L"Gamefixes_OPHFlagHack",	dest.Gamefixes.OPHFlagHack);
	dest.Gamefixes.SkipMPEGHack			= SetConf(ini, L"Gamefixes_SkipMPEGHack",	dest.Gamefixes.SkipMPEGHack);
	dest.Gamefixes.VuAddSubHack			= SetConf(ini, L"Gamefixes_VuAddSubHack",	dest.Gamefixes.VuAddSubHack);
	dest.Gamefixes.VuClipFlagHack		= SetConf(ini, L"Gamefixes_VuClipFlagHack",	dest.Gamefixes.VuClipFlagHack);
	dest.Gamefixes.XgKickHack			= SetConf(ini, L"Gamefixes_XgKickHack",		dest.Gamefixes.XgKickHack);

	dest.Cpu.Recompiler.UseMicroVU0		= SetConf(ini, L"Cpu_UseMicroVU0",			dest.Cpu.Recompiler.UseMicroVU0);
	dest.Cpu.Recompiler.UseMicroVU1		= SetConf(ini, L"Cpu_UseMicroVU1",			dest.Cpu.Recompiler.UseMicroVU1);
	//dest.Cpu.Recompiler.EnableVU0		= SetConf(ini, L"Cpu_EnableVU0",			dest.Cpu.Recompiler.EnableVU0);
	//dest.Cpu.Recompiler.EnableVU1		= SetConf(ini, L"Cpu_EnableVU1",			dest.Cpu.Recompiler.EnableVU1);
	//dest.Cpu.Recompiler.EnableIOP		= SetConf(ini, L"Cpu_EnableIOP",			dest.Cpu.Recompiler.EnableIOP);
	//dest.Cpu.Recompiler.EnableEE		= SetConf(ini, L"Cpu_EnableEE",				dest.Cpu.Recompiler.EnableEE);
	dest.Cpu.Recompiler.vuExtraOverflow = SetConf(ini, L"Cpu_vuExtraOverflow",		dest.Cpu.Recompiler.vuExtraOverflow);
	dest.Cpu.Recompiler.vuOverflow		= SetConf(ini, L"Cpu_vuOverflow_",			dest.Cpu.Recompiler.vuOverflow);
	dest.Cpu.Recompiler.vuSignOverflow	= SetConf(ini, L"Cpu_vuSignOverflow",		dest.Cpu.Recompiler.vuSignOverflow);
	dest.Cpu.Recompiler.vuUnderflow		= SetConf(ini, L"Cpu_vuUnderflow",			dest.Cpu.Recompiler.vuUnderflow);
	dest.Cpu.Recompiler.fpuExtraOverflow= SetConf(ini, L"Cpu_fpuExtraOverflow",		dest.Cpu.Recompiler.fpuExtraOverflow);
	dest.Cpu.Recompiler.fpuFullMode		= SetConf(ini, L"Cpu_fpuFullMode",			dest.Cpu.Recompiler.fpuFullMode);
	dest.Cpu.Recompiler.fpuOverflow		= SetConf(ini, L"Cpu_fpuOverflow",			dest.Cpu.Recompiler.fpuOverflow);
	dest.Cpu.sseVUMXCSR.DenormalsAreZero= SetConf(ini, L"Cpu_VU_DenormalsAreZero",	dest.Cpu.sseVUMXCSR.DenormalsAreZero);
	dest.Cpu.sseVUMXCSR.FlushToZero     = SetConf(ini, L"Cpu_VU_FlushToZero",		dest.Cpu.sseVUMXCSR.FlushToZero);
	dest.Cpu.sseVUMXCSR.RoundingControl = SetConf(ini, L"Cpu_VU_RoundingControl",	dest.Cpu.sseVUMXCSR.RoundingControl);
	dest.Cpu.sseMXCSR.DenormalsAreZero	= SetConf(ini, L"Cpu_FPU_DenormalsAreZero",	dest.Cpu.sseMXCSR.DenormalsAreZero);
	dest.Cpu.sseMXCSR.FlushToZero		= SetConf(ini, L"Cpu_FPU_FlushToZero",		dest.Cpu.sseMXCSR.FlushToZero);
	dest.Cpu.sseMXCSR.RoundingControl	= SetConf(ini, L"Cpu_FPU_RoundingControl",	dest.Cpu.sseMXCSR.RoundingControl);
}

wxString ConfigGame::GetGameId()
{
	wxString put;
	if(m_CRC == 0 || m_Serial == wxEmptyString) put = wxEmptyString;
	else put = wxString(L"_");
	return m_Serial + put + wxsFormat( L"%08X", m_CRC );
}

wxString ConfigGame::GetIniFolder(bool create)
{
	static u32		curCRC		= 0;
	static wxString curSerial	= wxEmptyString;
	static wxString GameIni		= wxEmptyString;

	if(m_CRC == 0 && m_Serial == wxEmptyString)
	{
		Console.Error("Loading Ini Folder Error: CRC and Serial = 0!");
		return wxEmptyString;
	}
	if(curCRC == m_CRC && curSerial == m_Serial && !create) return GameIni;

	curCRC		= m_CRC;
	curSerial	= m_Serial;

	wxDirName GameIniFolder( Path::Combine(SettingsFolder, GetGameId()) );
	if(create) GameIniFolder.Mkdir();
	GameIni = Path::Combine(GameIniFolder, wxString(L""));
	return GameIni;
}


Pcsx2Config ConfigGame::LoadConf(const u32& CRC, const wxString& Serial, const Pcsx2Config& _dest)
{
	dest = _dest;
	m_CRC = CRC;
	m_Serial = Serial;
	Console.WriteLn(L"Load: " + GetIniFolder() + L"Base.ini");
	wxFileConfig LoadGameIni( wxEmptyString, wxEmptyString, GetIniFolder() + L"Base.ini",
		wxEmptyString, wxCONFIG_USE_RELATIVE_PATH );

	IniLoader loader(LoadGameIni);
	Conf(loader);

	return dest;
}

void ConfigGame::SaveConf(const Pcsx2Config& _dest, const u32& CRC, const wxString& Serial)
{
	dest = _dest;
	Console.WriteLn(L"Save: " + GetIniFolder() + L"Base.ini");
	wxFileConfig SaveGameIni( wxEmptyString, wxEmptyString, GetIniFolder(true) + L"Base.ini", wxEmptyString, wxCONFIG_USE_RELATIVE_PATH );
	SaveGameIni.Create();

	IniSaver saver(SaveGameIni);
	Conf(saver);
}

enum ConfigurePluginBootons
{
	id_gs_booton = 0x999,
	id_spu2_booton,
	//id_cdvd_booton,
	id_pad_booton,
	id_dev9_booton,
	id_usb_booton,
	id_fw_booton
};

ConfigGameDialog::ConfigGameDialog( wxWindow* parent, const u32& CRC, const wxString& Serial )
	: wxDialogWithHelpers( parent, _("Config Game") )
	, m_CRC(CRC)
	, m_Serial(Serial)
{
	wxBoxSizer& s_buttons( *new wxBoxSizer(wxHORIZONTAL) );
	s_buttons += new wxButton( this, wxID_CANCEL )	| pxProportion(2);
	s_buttons += pxStretchSpacer(3);
	s_buttons += new wxButton( this, wxID_OK )		| pxProportion(2);

	wxStaticBoxSizer& s_confplugbootons = *new wxStaticBoxSizer(wxHORIZONTAL, this, _("Configure Plugins"));
	wxBoxSizer& s_plugbootons1( *new wxBoxSizer(wxVERTICAL) );
	wxBoxSizer& s_plugbootons2( *new wxBoxSizer(wxVERTICAL) );
	wxBoxSizer& s_plugbootons3( *new wxBoxSizer(wxVERTICAL) );

	s_plugbootons1 += new wxButton( this, id_gs_booton,		_("GS Plugin") )	| pxProportion(2);
	s_plugbootons1 += 5;
	s_plugbootons1 += new wxButton( this, id_spu2_booton,	_("SPU2 Plugin") )	| pxProportion(2);

	s_plugbootons2 += new wxButton( this, id_pad_booton,	_("PAD Plugin") )	| pxProportion(2);
	s_plugbootons2 += 5;
	s_plugbootons2 += new wxButton( this, id_dev9_booton,	_("DEV9 Plugin") )	| pxProportion(2);

	s_plugbootons3 += new wxButton( this, id_usb_booton,	_("USB Plugin") )	| pxProportion(2);
	s_plugbootons3 += 5;
	s_plugbootons3 += new wxButton( this, id_fw_booton,		_("FW Plugin") )	| pxProportion(2);

	s_confplugbootons += s_plugbootons1| pxBorder().Align( wxALIGN_CENTER_HORIZONTAL );
	s_confplugbootons += s_plugbootons2| pxBorder().Align( wxALIGN_CENTER_HORIZONTAL );
	s_confplugbootons += s_plugbootons3| pxBorder().Align( wxALIGN_CENTER_HORIZONTAL );


	const RadioPanelItem tbl_CpuTypes_VU[] =
	{
		RadioPanelItem(_("microVU"))
		.SetToolTip(_("New Vector Unit recompiler with much improved compatibility. Recommended.")),

		RadioPanelItem(_("superVU"))
		.SetToolTip(_("Useful for diagnosing bugs or clamping issues in the new mVU recompiler."))
	};

	m_panel_VU0 = &(new pxRadioPanel( this, tbl_CpuTypes_VU ))	->SetDefaultItem( 0 );
	m_panel_VU1 = &(new pxRadioPanel( this, tbl_CpuTypes_VU ))	->SetDefaultItem( 0 );

	wxStaticBoxSizer& s_eecycle   = *new wxStaticBoxSizer(wxVERTICAL, this, _("EE Cyclerate"));
	wxStaticBoxSizer& s_vustealer = *new wxStaticBoxSizer(wxVERTICAL, this, _("VU Cycle Stealing"));
	wxStaticBoxSizer& s_iopcycle  = *new wxStaticBoxSizer(wxVERTICAL, this, _("IOP Cyclerate"));
	m_slider_eecycle    = new wxSlider( this,  wxID_ANY, 1, 1, 4, wxDefaultPosition, wxDefaultSize, wxHORIZONTAL | wxSL_AUTOTICKS | wxSL_LABELS );
	m_slider_vustealer  = new wxSlider( this,  wxID_ANY, 0, 0, 4, wxDefaultPosition, wxDefaultSize, wxHORIZONTAL | wxSL_AUTOTICKS | wxSL_LABELS );
	m_slider_iopstealer = new wxSlider( this,  wxID_ANY, 0, 0, 3, wxDefaultPosition, wxDefaultSize, wxHORIZONTAL | wxSL_AUTOTICKS | wxSL_LABELS );

	s_eecycle	+= m_slider_eecycle;
	s_vustealer += m_slider_vustealer;
	s_iopcycle	+= m_slider_iopstealer;

	eeBranchHack	= new pxCheckBox( this, _("eeBranchHack")	);
	fastCDVD		= new pxCheckBox( this, _("fastCDVD")		);
	IntcStat		= new pxCheckBox( this, _("IntcStat")		);
	vuBlockHack		= new pxCheckBox( this, _("vuBlockHack")	);
	vuFlagHack		= new pxCheckBox( this, _("vuFlagHack")		);
	vuMinMax		= new pxCheckBox( this, _("vuMinMax")		);
	WaitLoop		= new pxCheckBox( this, _("WaitLoop")		);

	EETimingHack	= new pxCheckBox( this, _("EETimingHack")	);
	FpuCompareHack	= new pxCheckBox( this, _("FpuCompareHack")	);
	FpuMulHack		= new pxCheckBox( this, _("FpuMulHack")		);
	FpuNegDivHack	= new pxCheckBox( this, _("FpuNegDivHack")	);
	IPUWaitHack		= new pxCheckBox( this, _("IPUWaitHack")	);
	OPHFlagHack		= new pxCheckBox( this, _("OPHFlagHack")	);
	SkipMPEGHack	= new pxCheckBox( this, _("SkipMPEGHack")	);
	VuAddSubHack	= new pxCheckBox( this, _("VuAddSubHack")	);
	VuClipFlagHack	= new pxCheckBox( this, _("VuClipFlagHack")	);
	XgKickHack		= new pxCheckBox( this, _("XgKickHack")		);

	wxStaticBoxSizer& s_speedhacks = *new wxStaticBoxSizer(wxHORIZONTAL, this, _("Speedhacks"));
	wxStaticBoxSizer& s_gamefixes  = *new wxStaticBoxSizer(wxHORIZONTAL, this, _("Gamefixes"));

	wxBoxSizer& s_speedhackscyclepanel( *new wxBoxSizer(wxVERTICAL) );
	wxBoxSizer& s_speedhackboolpanel  ( *new wxBoxSizer(wxVERTICAL) );

	wxBoxSizer& s_checkbox( *new wxBoxSizer(wxVERTICAL) );

	s_checkbox += eeBranchHack;
	s_checkbox += fastCDVD;
	s_checkbox += IntcStat;
	s_checkbox += WaitLoop;

	s_checkbox += 8;

	s_checkbox += vuBlockHack;
	s_checkbox += vuFlagHack;
	s_checkbox += vuMinMax;

	s_speedhackscyclepanel += s_eecycle;
	s_speedhackscyclepanel += s_vustealer;
	s_speedhackscyclepanel += s_iopcycle;
	s_speedhackboolpanel   += s_checkbox;


	wxBoxSizer& s_checkboxf1( *new wxBoxSizer(wxVERTICAL) );
	wxBoxSizer& s_checkboxf2( *new wxBoxSizer(wxVERTICAL) );

	s_checkboxf1 += EETimingHack;
	s_checkboxf1 += FpuCompareHack;
	s_checkboxf1 += FpuMulHack;
	s_checkboxf1 += FpuNegDivHack;
	s_checkboxf1 += IPUWaitHack;
	s_checkboxf2 += OPHFlagHack;
	s_checkboxf2 += SkipMPEGHack;
	s_checkboxf2 += VuAddSubHack;
	s_checkboxf2 += VuClipFlagHack;
	s_checkboxf2 += XgKickHack;

	s_gamefixes += s_checkboxf1 | pxBorder().Align( wxALIGN_TOP );
	s_gamefixes += s_checkboxf2 | pxBorder().Align( wxALIGN_TOP );

	s_speedhacks += s_speedhackscyclepanel	| pxBorder().Align( wxALIGN_TOP );
	s_speedhacks += 5;
	s_speedhacks += s_speedhackboolpanel	| pxBorder().Align( wxALIGN_TOP );

	wxBoxSizer& s_panel( *new wxBoxSizer(wxHORIZONTAL) );
	wxBoxSizer& s_panel2( *new wxBoxSizer(wxVERTICAL) );

	wxBoxSizer& s_panelFandB( *new wxBoxSizer(wxVERTICAL) );

	s_panelFandB  += s_gamefixes       | pxBorder().Align( wxALIGN_TOP );
	s_panelFandB  += 5;
	s_panelFandB  += s_confplugbootons | pxBorder().Align( wxALIGN_TOP );

	wxStaticBoxSizer& s_vu		= *new wxStaticBoxSizer(wxHORIZONTAL, this, _("VU"));	

	wxStaticBoxSizer& s_vu0		= *new wxStaticBoxSizer(wxVERTICAL, this, _("VU0 Recompilers"));	
	wxStaticBoxSizer& s_vu1		= *new wxStaticBoxSizer(wxVERTICAL, this, _("VU1 Recompilers"));
	s_vu0 += m_panel_VU0 | StdExpand();
	s_vu1 += m_panel_VU1 | StdExpand();

	m_panel_VU0->Realize();
	m_panel_VU1->Realize();

	m_VU_FTZ = new pxCheckBox( this, _("Flush to Zero") );
	m_VU_DAZ = new pxCheckBox( this, _("Denormals are Zero") );

	wxStaticBoxSizer*	s_vu_round( new wxStaticBoxSizer( wxVERTICAL, this, _("Round Mode") ) );
	wxStaticBoxSizer*	s_vu_clamp( new wxStaticBoxSizer( wxVERTICAL, this, _("Clamping Mode") ) );

	wxBoxSizer& s_panel_vu( *new wxBoxSizer(wxHORIZONTAL) );
	s_panel_vu += s_vu0;
	s_panel_vu += s_vu1;

	const RadioPanelItem VU_RoundModeChoices[] =
	{
		RadioPanelItem(_("Nearest")),
		RadioPanelItem(_("Negative")),
		RadioPanelItem(_("Positive")),
		RadioPanelItem(_("Chop / Zero"))
	};

	const RadioPanelItem VU_ClampModeChoices[] =
	{
		RadioPanelItem(_("None")),
		RadioPanelItem(_("Normal")),
		RadioPanelItem(_("Extra")),
		RadioPanelItem(_("Extra + Preserve Sign")),
	};

	m_VU_RoundModePanel = new pxRadioPanel( this, VU_RoundModeChoices );
	m_VU_ClampModePanel = new pxRadioPanel( this, VU_ClampModeChoices );
	
	*s_vu_round += m_VU_RoundModePanel;
	*s_vu_clamp += m_VU_ClampModePanel;

	m_VU_RoundModePanel->SetDefaultItem( 3 );
	m_VU_ClampModePanel->SetDefaultItem( 1 );

	m_VU_RoundModePanel->Realize();
	m_VU_ClampModePanel->Realize();

	s_panel_vu += s_vu_round;
	s_panel_vu += s_vu_clamp;

	wxBoxSizer& s_panel_vu_FTZ_DAZ( *new wxBoxSizer(wxVERTICAL) );
	s_panel_vu_FTZ_DAZ += m_VU_FTZ;
	s_panel_vu_FTZ_DAZ += m_VU_DAZ;

	s_panel_vu += s_panel_vu_FTZ_DAZ;

	s_vu += s_panel_vu;



	wxStaticBoxSizer& s_fpu = *new wxStaticBoxSizer(wxHORIZONTAL, this, _("EE/IOP"));

	m_FPU_FTZ = new pxCheckBox( this, _("Flush to Zero") );
	m_FPU_DAZ = new pxCheckBox( this, _("Denormals are Zero") );

	wxStaticBoxSizer*	s_fpu_round( new wxStaticBoxSizer( wxVERTICAL, this, _("Round Mode") ) );
	wxStaticBoxSizer*	s_fpu_clamp( new wxStaticBoxSizer( wxVERTICAL, this, _("Clamping Mode") ) );

	wxBoxSizer& s_panel_fpu( *new wxBoxSizer(wxHORIZONTAL) );

	const RadioPanelItem FPU_RoundModeChoices[] =
	{
		RadioPanelItem(_("Nearest")),
		RadioPanelItem(_("Negative")),
		RadioPanelItem(_("Positive")),
		RadioPanelItem(_("Chop / Zero"))
	};

	const RadioPanelItem FPU_ClampModeChoices[] =
	{
		RadioPanelItem(_("None")),
		RadioPanelItem(_("Normal")),
		RadioPanelItem(_("Extra + Preserve Sign")),
		RadioPanelItem(_("Full")),
	};

	m_FPU_RoundModePanel = new pxRadioPanel( this, FPU_RoundModeChoices );
	m_FPU_ClampModePanel = new pxRadioPanel( this, FPU_ClampModeChoices );
	
	*s_fpu_round += m_FPU_RoundModePanel;
	*s_fpu_clamp += m_FPU_ClampModePanel;

	m_FPU_RoundModePanel->SetDefaultItem( 3 );
	m_FPU_ClampModePanel->SetDefaultItem( 1 );

	m_FPU_RoundModePanel->Realize();
	m_FPU_ClampModePanel->Realize();

	s_panel_fpu += s_fpu_round;
	s_panel_fpu += s_fpu_clamp;

	wxBoxSizer& s_panel_fpu_FTZ_DAZ( *new wxBoxSizer(wxVERTICAL) );
	s_panel_fpu_FTZ_DAZ += m_FPU_FTZ;
	s_panel_fpu_FTZ_DAZ += m_FPU_DAZ;

	s_panel_fpu += s_panel_fpu_FTZ_DAZ;

	s_fpu += s_panel_fpu;

	s_panel		+= s_speedhacks		| pxBorder().Align( wxALIGN_TOP );
	s_panel		+= pxStretchSpacer(5);
	s_panel		+= s_panelFandB		| pxBorder().Align( wxALIGN_TOP );

	s_panel2	+= s_panel;
	s_panel2	+= s_vu				| pxBorder().Align( wxALIGN_TOP );
	s_panel2	+= s_fpu			| pxBorder().Align( wxALIGN_TOP );
	s_panel2	+= s_buttons		| pxBorder().Align( wxALIGN_CENTER_HORIZONTAL );

	*this += s_panel2	  | StdExpand();

	Connect( wxEVT_SCROLL_PAGEUP,	wxScrollEventHandler( ConfigGameDialog::Slider_Click ) );
	Connect( wxEVT_SCROLL_PAGEDOWN,	wxScrollEventHandler( ConfigGameDialog::Slider_Click ) );
	Connect( wxEVT_SCROLL_LINEUP,	wxScrollEventHandler( ConfigGameDialog::Slider_Click ) );
	Connect( wxEVT_SCROLL_LINEDOWN,	wxScrollEventHandler( ConfigGameDialog::Slider_Click ) );
	Connect( wxEVT_SCROLL_TOP,		wxScrollEventHandler( ConfigGameDialog::Slider_Click ) );
	Connect( wxEVT_SCROLL_BOTTOM,	wxScrollEventHandler( ConfigGameDialog::Slider_Click ) );

	Connect( wxID_OK,			wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigGameDialog::OnOk_Click ) );

	Connect( id_gs_booton,		wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigGameDialog::ConfigGSPlugin	) );
	Connect( id_spu2_booton,	wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigGameDialog::ConfigSPU2Plugin ) );
	//Connect( id_cdvd_booton,	wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigGameDialog::ConfigCDVDPlugin ) );
	Connect( id_pad_booton,		wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigGameDialog::ConfigPADPlugin	) );
	Connect( id_dev9_booton,	wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigGameDialog::ConfigDEV9Plugin ) );
	Connect( id_usb_booton,		wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigGameDialog::ConfigUSBPlugin	) );
	Connect( id_fw_booton,		wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigGameDialog::ConfigFWPlugin	) );

	LoadConfig();

}

void ConfigGameDialog::ConfigGSPlugin  ( wxCommandEvent& event ){ConfigurePlugin(PluginId_GS);	}
void ConfigGameDialog::ConfigSPU2Plugin( wxCommandEvent& event ){ConfigurePlugin(PluginId_SPU2);}
void ConfigGameDialog::ConfigCDVDPlugin( wxCommandEvent& event ){ConfigurePlugin(PluginId_CDVD);}
void ConfigGameDialog::ConfigPADPlugin ( wxCommandEvent& event ){ConfigurePlugin(PluginId_PAD);	}
void ConfigGameDialog::ConfigDEV9Plugin( wxCommandEvent& event ){ConfigurePlugin(PluginId_DEV9);}
void ConfigGameDialog::ConfigUSBPlugin ( wxCommandEvent& event ){ConfigurePlugin(PluginId_USB);	}
void ConfigGameDialog::ConfigFWPlugin  ( wxCommandEvent& event ){ConfigurePlugin(PluginId_FW);	}

void ConfigGameDialog::LoadConfig()
{
	dest = LoadConf(m_CRC, m_Serial);

	if( dest.Cpu.Recompiler.UseMicroVU0 )
		m_panel_VU0->SetSelection( 0 );
	else
		m_panel_VU0->SetSelection( 1 );

	if( dest.Cpu.Recompiler.UseMicroVU1 )
		m_panel_VU1->SetSelection( 0 );
	else
		m_panel_VU1->SetSelection( 1 );


	if		( dest.Cpu.Recompiler.vuSignOverflow )	m_VU_ClampModePanel->SetSelection( 3 );
	else if ( dest.Cpu.Recompiler.vuExtraOverflow )	m_VU_ClampModePanel->SetSelection( 2 );
	else if ( dest.Cpu.Recompiler.vuOverflow )		m_VU_ClampModePanel->SetSelection( 1 );
	else											m_VU_ClampModePanel->SetSelection( 0 );

	m_VU_FTZ->SetValue( dest.Cpu.sseVUMXCSR.FlushToZero );
	m_VU_DAZ->SetValue( dest.Cpu.sseVUMXCSR.DenormalsAreZero );

	m_VU_RoundModePanel->SetSelection( dest.Cpu.sseVUMXCSR.RoundingControl );

	m_FPU_FTZ->SetValue( dest.Cpu.sseMXCSR.FlushToZero );
	m_FPU_DAZ->SetValue( dest.Cpu.sseMXCSR.DenormalsAreZero );

	m_FPU_RoundModePanel->SetSelection( dest.Cpu.sseMXCSR.RoundingControl );

	if( dest.Cpu.Recompiler.fpuFullMode )			m_FPU_ClampModePanel->SetSelection( 3 );
	else if( dest.Cpu.Recompiler.fpuExtraOverflow )	m_FPU_ClampModePanel->SetSelection( 2 );
	else if( dest.Cpu.Recompiler.fpuOverflow )		m_FPU_ClampModePanel->SetSelection( 1 );
	else											m_FPU_ClampModePanel->SetSelection( 0 );

	m_slider_eecycle	->SetValue(dest.Speedhacks.EECycleRate+1);
	m_slider_vustealer	->SetValue(dest.Speedhacks.VUCycleSteal	);
	m_slider_iopstealer	->SetValue(dest.Speedhacks.IOPCycleSteal);

	eeBranchHack		->SetValue(dest.Speedhacks.eeBranchHack	);
	fastCDVD			->SetValue(dest.Speedhacks.fastCDVD		);
	IntcStat			->SetValue(dest.Speedhacks.IntcStat		);
	vuBlockHack			->SetValue(dest.Speedhacks.vuBlockHack	);
	vuFlagHack			->SetValue(dest.Speedhacks.vuFlagHack	);
	vuMinMax			->SetValue(dest.Speedhacks.vuMinMax		);
	WaitLoop			->SetValue(dest.Speedhacks.WaitLoop		);

	EETimingHack		->SetValue(dest.Gamefixes.EETimingHack	);
	FpuCompareHack		->SetValue(dest.Gamefixes.FpuCompareHack);
	FpuMulHack			->SetValue(dest.Gamefixes.FpuMulHack	);
	FpuNegDivHack		->SetValue(dest.Gamefixes.FpuNegDivHack	);
	IPUWaitHack			->SetValue(dest.Gamefixes.IPUWaitHack	);
	OPHFlagHack			->SetValue(dest.Gamefixes.OPHFlagHack	);
	SkipMPEGHack		->SetValue(dest.Gamefixes.SkipMPEGHack	);
	VuAddSubHack		->SetValue(dest.Gamefixes.VuAddSubHack	);
	VuClipFlagHack		->SetValue(dest.Gamefixes.VuClipFlagHack);
	XgKickHack			->SetValue(dest.Gamefixes.XgKickHack	);
}

void ConfigGameDialog::OnOk_Click( wxCommandEvent& event )
{
	//dest.Cpu.Recompiler.EnableVU0	= true;
	//dest.Cpu.Recompiler.EnableVU1	= true;

	dest.Cpu.Recompiler.UseMicroVU0	= m_panel_VU0->GetSelection() == 0;
	dest.Cpu.Recompiler.UseMicroVU1	= m_panel_VU1->GetSelection() == 0;

	dest.Speedhacks.EECycleRate	  = m_slider_eecycle	->GetValue()-1;
	dest.Speedhacks.VUCycleSteal  = m_slider_vustealer	->GetValue();
	dest.Speedhacks.IOPCycleSteal = m_slider_iopstealer	->GetValue();

	dest.Cpu.sseVUMXCSR = Pcsx2Config::CpuOptions().sseVUMXCSR;	//set default

	dest.Cpu.sseVUMXCSR.RoundingControl	= m_VU_RoundModePanel->GetSelection();
	dest.Cpu.sseVUMXCSR.DenormalsAreZero= m_VU_DAZ->GetValue();
	dest.Cpu.sseVUMXCSR.FlushToZero		= m_VU_FTZ->GetValue();

	Pcsx2Config::CpuOptions& cpuOps( g_Conf->EmuOptions.Cpu );
	Pcsx2Config::RecompilerOptions& recOps( cpuOps.Recompiler );

	cpuOps.sseMXCSR = Pcsx2Config::CpuOptions().sseMXCSR;		// set default

	dest.Cpu.sseMXCSR.RoundingControl	= m_FPU_RoundModePanel->GetSelection();
	dest.Cpu.sseMXCSR.DenormalsAreZero	= m_FPU_DAZ->GetValue();
	dest.Cpu.sseMXCSR.FlushToZero		= m_FPU_FTZ->GetValue();

	const int clampSelFPU		= m_FPU_ClampModePanel->GetSelection();

	dest.Cpu.Recompiler.fpuOverflow		= clampSelFPU >= 1;
	dest.Cpu.Recompiler.fpuExtraOverflow= clampSelFPU >= 2;
	dest.Cpu.Recompiler.fpuFullMode		= clampSelFPU >= 3;

	const int clampSel			= m_VU_ClampModePanel->GetSelection();
	dest.Cpu.Recompiler.vuOverflow		= clampSel >= 1;
	dest.Cpu.Recompiler.vuExtraOverflow	= clampSel >= 2;
	dest.Cpu.Recompiler.vuSignOverflow	= clampSel >= 3;

	dest.Speedhacks.eeBranchHack	 = eeBranchHack		->GetValue();
	dest.Speedhacks.fastCDVD 		 = fastCDVD			->GetValue();
	dest.Speedhacks.IntcStat		 = IntcStat			->GetValue();
	dest.Speedhacks.vuBlockHack		 = vuBlockHack		->GetValue();
	dest.Speedhacks.vuFlagHack		 = vuFlagHack		->GetValue();
	dest.Speedhacks.vuMinMax		 = vuMinMax			->GetValue();
	dest.Speedhacks.WaitLoop		 = WaitLoop			->GetValue();

	dest.Gamefixes.EETimingHack		 = EETimingHack		->GetValue();
	dest.Gamefixes.FpuCompareHack	 = FpuCompareHack	->GetValue();
	dest.Gamefixes.FpuMulHack		 = FpuMulHack		->GetValue();
	dest.Gamefixes.FpuNegDivHack	 = FpuNegDivHack	->GetValue();
	dest.Gamefixes.IPUWaitHack		 = IPUWaitHack		->GetValue();
	dest.Gamefixes.OPHFlagHack		 = OPHFlagHack		->GetValue();
	dest.Gamefixes.SkipMPEGHack		 = SkipMPEGHack		->GetValue();
	dest.Gamefixes.VuAddSubHack		 = VuAddSubHack		->GetValue();
	dest.Gamefixes.VuClipFlagHack	 = VuClipFlagHack	->GetValue();
	dest.Gamefixes.XgKickHack		 = XgKickHack		->GetValue();

	SaveConf(dest, m_CRC, m_Serial);
	EndModal( wxID_OK );
}

void ConfigGameDialog::Slider_Click(wxScrollEvent &event)
{
	wxSlider* slider = (wxSlider*) event.GetEventObject();
	int value = slider->GetValue();
	int eventType = event.GetEventType();
	if (eventType == wxEVT_SCROLL_PAGEUP || eventType == wxEVT_SCROLL_LINEUP) {
		if (value > slider->GetMin()) {
			slider->SetValue(value-1);
		}
	}
	else if (eventType == wxEVT_SCROLL_TOP) {
		slider->SetValue(slider->GetMin());
	}
	else if (eventType == wxEVT_SCROLL_PAGEDOWN || eventType == wxEVT_SCROLL_LINEDOWN) {
		if (value < slider->GetMax()) {
			slider->SetValue(value+1);
		}
	}
	else if (eventType == wxEVT_SCROLL_BOTTOM) {
		slider->SetValue(slider->GetMax());
	}

	event.Skip();
}

/*
bool GameListItem::operator==( const GameListItem& right ) const
{
	return OpEqu(GamesName)     && OpEqu(gameFileSizeMB)	
		&& OpEqu(showtype)		&& OpEqu(showdisctype)	
		&& OpEqu(crc)	        && OpEqu(gamesize)	
		&& OpEqu(DateCreated)	&& OpEqu(DateModified)
		&& OpEqu(Serial);
}

bool GameListItem::operator!=( const GameListItem& right ) const
{
	return operator==( right );
}
*/
using namespace pxSizerFlags;

enum GameMenuId
{
	GameMenuId_Delete = 0x888,
	GameMenuId_RefreshList,
	GameMenuId_BootIso,
	GameMenuId_SkipBIOS,
	GameMenuId_Compress_Z3,
	GameMenuId_Compress_BZ2,
	GameMenuId_Compress_Z2,
	GameMenuId_Compress_Z,
	GameMenuId_Resume_Compress,
	GameMenuId_Decompress,
	GameMenuId_DefaultSizeAllCol,
	GameMenuId_RenameGame,
	GameMenuId_ResumeGame,
	GameMenuId_PauseGame,
	GameMenuId_ResetGame,
	GameMenuId_StopGame,
	GameMenuId_SetSettingsGame,

	GameMenuId_ColEnable
};

// =====================================================================================================
//  GameSelectorPanel
// =====================================================================================================

//#define USEBLOCKDUMPING
Panels::GameSelectorPanel::GameSelectorPanel( wxWindow* parent )
	: BaseSelectorPanel( parent )
{
	SetMinSize( wxSize( GetMinWidth(), GetMinHeight() ) );
	if( wxSizer* sizer = GetSizer() )
		sizer->SetMinSize( wxSize( sizer->GetMinSize().GetWidth() + 15, sizer->GetMinSize().GetHeight() + 15 ) );
	
	m_FolderPicker = new DirPickerPanel( this, FolderId_Games,_("Select folder with PS2 games"));// dir picker popup label
	
	wxBoxSizer& s_buttons(*new wxBoxSizer( wxHORIZONTAL ));
	s_leftside_buttons	=  new wxBoxSizer( wxHORIZONTAL );
	s_rightside_buttons	=  new wxBoxSizer( wxHORIZONTAL );

	s_buttons += s_leftside_buttons		| pxAlignLeft;
	s_buttons += pxStretchSpacer();
	s_buttons += s_rightside_buttons	| pxAlignRight;

	m_listview = new GameSelectorPanel_List(this);
	m_listview->SetMinSize( wxSize( std::max( m_listview->GetMinSize().GetWidth(), 715 ), std::max( m_listview->GetMinSize().GetHeight(), 500 ) ) );
	

	BootCDVDButton   = new wxButton( this, wxID_ANY,   _("Boot Plugin")  );
	refreshButton    = new wxButton( this, wxID_ANY,   _("Refresh list") );
	DeleteGameButton = new wxButton( this, wxID_ANY,   _("Delete")       );

#ifdef USEBLOCKDUMPING
			  m_BlockDumping   = new pxCheckBox( this, _("Enable Block Dumping"));
#endif
			  m_ENABLEskipBIOS = new pxCheckBox( this, _("Enable Skip BIOS")    );

	*this   += m_FolderPicker | pxExpand;
	*this	+= 5;
	*this	+= Label(_("Select a game:"));
	*this   += m_listview		| pxExpand;
	*this   += s_buttons		| pxExpand;

	*s_leftside_buttons     	+= refreshButton;
	*s_leftside_buttons     	+= 8;
	*s_leftside_buttons     	+= DeleteGameButton;
	*s_leftside_buttons     	+= 8;
	*s_leftside_buttons         += BootCDVDButton;
	*s_leftside_buttons         += 8;

	*s_rightside_buttons     	+= m_ENABLEskipBIOS;
#ifdef USEBLOCKDUMPING
	*s_rightside_buttons     	+= m_BlockDumping;
#endif

	DeleteGameButton->Disable();

	for(int i = 0; i < GameCol_Count; ++i)
	Connect( GameMenuId_ColEnable + i,   wxEVT_COMMAND_MENU_SELECTED,        wxCommandEventHandler( GameSelectorPanel::ColShowClick)           );

	Connect( GameMenuId_SetSettingsGame, wxEVT_COMMAND_MENU_SELECTED,        wxCommandEventHandler( GameSelectorPanel::GameSttings )           );

	Connect( GameMenuId_ResumeGame,      wxEVT_COMMAND_MENU_SELECTED,        wxCommandEventHandler( GameSelectorPanel::ResumeGame )            );
	Connect( GameMenuId_PauseGame,       wxEVT_COMMAND_MENU_SELECTED,        wxCommandEventHandler( GameSelectorPanel::PauseGame )             );
	Connect( GameMenuId_ResetGame,       wxEVT_COMMAND_MENU_SELECTED,        wxCommandEventHandler( GameSelectorPanel::ResetGame )             );
	Connect( GameMenuId_StopGame,        wxEVT_COMMAND_MENU_SELECTED,        wxCommandEventHandler( GameSelectorPanel::StopGame )              );

	Connect(GameMenuId_DefaultSizeAllCol,wxEVT_COMMAND_MENU_SELECTED,        wxCommandEventHandler( GameSelectorPanel::RestoreDefaultsColumnsWidth));
	Connect( GameMenuId_RenameGame,      wxEVT_COMMAND_MENU_SELECTED,        wxCommandEventHandler( GameSelectorPanel::OnRenameGame)           );

	Connect( GameMenuId_Delete,	         wxEVT_COMMAND_MENU_SELECTED,        wxCommandEventHandler( GameSelectorPanel::OnDeleteGame)           );
	Connect( GameMenuId_RefreshList,     wxEVT_COMMAND_MENU_SELECTED,        wxCommandEventHandler( GameSelectorPanel::OnRefreshSelections)    );
	Connect( GameMenuId_BootIso,         wxEVT_COMMAND_MENU_SELECTED,        wxCommandEventHandler( GameSelectorPanel::BootGameIso)            );

	Connect( GameMenuId_Compress_Z,      wxEVT_COMMAND_MENU_SELECTED,        wxCommandEventHandler( GameSelectorPanel::Compress_Z)             );
	Connect( GameMenuId_Compress_Z2,     wxEVT_COMMAND_MENU_SELECTED,        wxCommandEventHandler( GameSelectorPanel::Compress_Z2)            );
	Connect( GameMenuId_Compress_BZ2,    wxEVT_COMMAND_MENU_SELECTED,        wxCommandEventHandler( GameSelectorPanel::Compress_BZ2)           );
	Connect( GameMenuId_Compress_Z3,     wxEVT_COMMAND_MENU_SELECTED,        wxCommandEventHandler( GameSelectorPanel::Compress_Z3)            );
	Connect( GameMenuId_Resume_Compress, wxEVT_COMMAND_MENU_SELECTED,		 wxCommandEventHandler( GameSelectorPanel::Compress_Resume)        );
	Connect( GameMenuId_Decompress,      wxEVT_COMMAND_MENU_SELECTED,        wxCommandEventHandler( GameSelectorPanel::Decompress)             );

	Connect( refreshButton->GetId(),     wxEVT_COMMAND_BUTTON_CLICKED,       wxCommandEventHandler( GameSelectorPanel::OnRefreshSelections)    );
	Connect( DeleteGameButton->GetId(),  wxEVT_COMMAND_BUTTON_CLICKED,       wxCommandEventHandler( GameSelectorPanel::OnDeleteGame)           );
	Connect( BootCDVDButton->GetId(),    wxEVT_COMMAND_BUTTON_CLICKED,       wxCommandEventHandler( GameSelectorPanel::BootGameCDVD)           );

	Connect( m_listview->GetId(),        wxEVT_COMMAND_LIST_ITEM_SELECTED,   wxListEventHandler( GameSelectorPanel::UpdateBootons)             );
	Connect( m_listview->GetId(),        wxEVT_COMMAND_LIST_ITEM_DESELECTED, wxListEventHandler( GameSelectorPanel::UpdateBootons)             );
	Connect( m_listview->GetId(),        wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK,wxListEventHandler( GameSelectorPanel::OnOpenItemContextMenu)     );
	Connect( m_listview->GetId(),        wxEVT_COMMAND_LIST_ITEM_ACTIVATED,  wxListEventHandler( GameSelectorPanel::BootGameIsoDClick)         );
	Connect( m_listview->GetId(),        wxEVT_COMMAND_LIST_COL_RIGHT_CLICK, wxListEventHandler( GameSelectorPanel::ColRightClick)             );
	//Connect( m_listview->GetId(),        wxEVT_COMMAND_LIST_COL_END_DRAG,    wxListEventHandler(GameSelectorPanel::SaveColSize)                );
	LoadColShow();
	UpdateBootons();
}

void Panels::GameSelectorPanel::GameSttings( wxCommandEvent& evt )
{
	int sel = m_listview->GetFirstSelected();
	GameListItem& item( m_Games[sel] );

	wxWindowID result = ConfigGameDialog( this, item.crc, item.Serial ).ShowModal();
	if(result == wxID_OK)
	{
		//RefreshList();
	}
}

void Panels::GameSelectorPanel::SaveColSize()
{
	IniSaver saver;
	ScopedIniGroup group( saver, L"GameListPanel" );
	m_listview->LoadSaveColumns(saver);
}

void Panels::GameSelectorPanel::LoadColSize()
{
	IniLoader loader;
	ScopedIniGroup group( loader, L"GameListPanel" );
	m_listview->LoadSaveColumns(loader);
}

void Panels::GameSelectorPanel::ColShowClick( wxCommandEvent& evt )
{
	int a = evt.GetId();
	int count = 0;

	for(int i = 0; i < GameCol_Count; ++i)
	{
		if( a == (GameMenuId_ColEnable + i) ) 
		{
			count = i;
			break;
		}
	}

	ShowCol[count] = !ShowCol[count];

	IniSaver saver;
	ScopedIniGroup group( saver, L"GameListPanel" );

	FastFormatUnicode label;
	const GameListViewColumnInfo& cinfo = m_listview->GetDefaultColumnInfo(count);

	label.Clear();
	label.Write( L"Column_%s", cinfo.name );
	bool defaultshow = true;
	if((count == GameCol_DateModified) || (count == GameCol_DateCreated))
	{
		defaultshow = false;
	}

	saver.Entry( label, ShowCol[count], defaultshow );

	if(!ShowCol[count])
	{
		int width = m_listview->GetColumnWidth(count);
		label.Clear();
		label.Write( L"ColumnWidth_%s", cinfo.name );
		saver.Entry( label, width, cinfo.width );
	}

	SaveColShow(count);
}

void Panels::GameSelectorPanel::SaveColShow(int save_loadwith)
{
	IniSaver saver;
	ScopedIniGroup group( saver, L"GameListPanel" );
	LoadSaveShowColumns(saver, save_loadwith);
}

void Panels::GameSelectorPanel::RestoreDefaultsColumnsWidth( wxCommandEvent& evt )
{
	wxString content;
	content.Printf( _T( "You sure restore defaults columns width?" ));

	if( !Msgbox::YesNo( content, _("You sure?") ) ) return;

	for( uint col=0; col<GameCol_Count; ++col )
	{
		const GameListViewColumnInfo& cinfo = m_listview->GetDefaultColumnInfo(col);
		m_listview->SetColumnWidth(col, cinfo.width);
	}
	content.Clear();
	content.Printf( _T( "Save default settings?" ) );

	if( !Msgbox::YesNo( content, _("Save settings") ) ) return;
	SaveColSize();
}

void Panels::GameSelectorPanel::LoadColShow()
{
	IniLoader loader;
	ScopedIniGroup group( loader, L"GameListPanel" );
	LoadSaveShowColumns(loader);
}

void Panels::GameSelectorPanel::LoadSaveShowColumns( IniInterface& ini, int save_loadwith )
{
	FastFormatUnicode label;
	int width[GameCol_Count];

	int i = 0;
	bool en[GameCol_Count] = {false};
	if(!ini.IsLoading())
	{
		for( uint col=0; col<GameCol_Count; ++col )
		{
			const GameListViewColumnInfo& cinfo = m_listview->GetDefaultColumnInfo(col);
			if(!ShowCol[col] || (save_loadwith == col && ShowCol[col]) )
			{
				IniLoader loader;
				ScopedIniGroup group( loader, L"GameListPanel" );
				label.Clear();
				label.Write( L"ColumnWidth_%s", cinfo.name );
				loader.Entry( label, width[col], cinfo.width ); // load saved columns width
				while(true)
				{
					i++;
					if(col+i>GameCol_Count)break;
					if(ShowCol[col+i])
					{
						width[col+i] = m_listview->GetColumnWidth(col+i);
						break;
					}
					else
					{
						en[col+i] = true;
					}
				}
			}
			else
			{
				if(col+i <= GameCol_Count)
				{
					width[col+i] = m_listview->GetColumnWidth(col+i);
				}
			}
			if(en[col])
			{
				width[col] = m_listview->GetColumnWidth(col);
			}
		}
		m_listview->DeleteAllColumns();
	}

	for( uint col=0; col<GameCol_Count; ++col )
	{
		const GameListViewColumnInfo& cinfo = m_listview->GetDefaultColumnInfo(col);
		if(ini.IsLoading())
		{
			label.Clear();
			label.Write( L"Column_%s", cinfo.name );
			bool defaultshow = true;
			if((col == GameCol_DateModified) || (col == GameCol_DateCreated))
			{
				defaultshow = false;
			}
			ini.Entry( label, ShowCol[col], defaultshow );
		}
		
		if(ShowCol[col])
		{
			if(save_loadwith == -1)
			{
				label.Clear();
				label.Write( L"ColumnWidth_%s", cinfo.name );
				ini.Entry( label, width[col], cinfo.width );
			}
			m_listview->InsertColumn(col, pxGetTranslation(cinfo.name), cinfo.align, width[col] > 0 ? width[col] : cinfo.width);// if error then set default width
		}
	}

	if( !ini.IsLoading() )
	{
		for(int item = 0; item < m_listview->GetItemCount(); item++)
		{
			UpdateItemCol( m_Games[item] );
		}
		m_listview->RefreshItems(0, m_listview->GetItemCount());
	}
}

void Panels::GameSelectorPanel::ColRightClick( wxListEvent& evt )
{
	int idx = evt.GetIndex();

	wxMenu* junk = new wxMenu();

	for(int i = 0; i < GameCol_Count; ++i)
	{
		const GameListViewColumnInfo& cinfo = m_listview->GetDefaultColumnInfo(i);
		junk->AppendCheckItem(GameMenuId_ColEnable + i,	(_("%s"), cinfo.name));
		junk->Check( GameMenuId_ColEnable + i, ShowCol[i] );
	}
	junk->AppendSeparator();

	junk->Append(GameMenuId_DefaultSizeAllCol,	_("Restore Defaults Columns Width"));
	
	PopupMenu( junk );
	UpdateBootons();
}

enum Compress_Mode
{
	DecompressMode = 0,
	Compress_to_Z,
	Compress_to_Z2,
	Compress_to_BZ2,
	Compress_to_Z3
};

void Panels::GameSelectorPanel::Compress(int format)
{
	int sel = m_listview->GetFirstSelected();
	GameListItem& item( m_Games[sel] );

	wxString showformat;
	if( format == Compress_to_Z2 )			showformat = L".Z2";
	else if( format == Compress_to_BZ2 )	showformat = L".BZ2";
	else if( format == Compress_to_Z3 )		showformat = L".Z3";
	else if( format == DecompressMode ) {}
	else { Console.Error(L"COMPRESS ERROR: Unknown compress mode!"); return; }
	
	wxString content;
	content.Printf( L"You sure %scompress %s%s%s?", format==DecompressMode ? L"de" : L"",
		item.Game.GetName().c_str(),format==DecompressMode?L"":L" to ", format==DecompressMode?L"":showformat.c_str() );

	if( !Msgbox::YesNo( content, (_T("%s"),format==DecompressMode ? L"Decompress game" : L"Compress game")) ) return;

	u32 lsn;
	u8 cdbuff[CD_FRAMESIZE_RAW];
	isoFile src, dst;

	wxString SrcFileName ( item.Game.GetFullPath() );
	wxString PathNameFile( Path::Combine(m_FolderPicker->GetPath().ToString(), item.Game.GetName()) );
	wxString StringFormat( format==DecompressMode ? L".iso" : showformat );
	wxString DstFileName ( PathNameFile + StringFormat );
	wxString TmpFileName ( DstFileName + L".tmp");

	wxFile fp;
	if( fp.Access(DstFileName, fp.read) )
	{
		if(!content.IsEmpty())content.Clear();
		content.Printf( L"%s%s found on disk. Delete %s%s?", 
			item.GameName.c_str(), format==DecompressMode ? L".iso" : showformat.c_str(), 
			item.GameName.c_str(), format==DecompressMode ? L".iso" : showformat.c_str()
		);

		if( !Msgbox::YesNo( content, _("Warning") ) ) return;
		/*
		wxRemoveFile(DstFileName);
		if(format!=DecompressMode)
		{
			wxRemoveFile(DstFileName + L".table");
		}
		*/
	}

	src.Open( SrcFileName );

	if( format == Compress_to_Z2 )
		dst.Create(TmpFileName, ISOFLAGS_Z2);
	else if( format == Compress_to_BZ2 )
		dst.Create(TmpFileName, ISOFLAGS_BZ2);
	else if( format == Compress_to_Z3 )
		dst.Create(TmpFileName, ISOFLAGS_Z3);
	else if( format==DecompressMode )
		dst.Create(TmpFileName, 0);
	else
	{
		Console.Error(L"Error compress!");
		return;
	}

	dst.WriteFormat(src.GetBlockOffset(), src.GetBlockSize(), src.GetBlockCount());

	wxProgressDialog 
		dialog(
		(_T("%s"), format==DecompressMode ? L"Decompressing ISO" : L"Compressing ISO"),
		_T("Loading..."),
		10000, // range
		this, // parent
		wxPD_APP_MODAL		|
		wxPD_ELAPSED_TIME	|
		wxPD_ESTIMATED_TIME |
		wxPD_REMAINING_TIME |
		wxPD_CAN_SKIP		|
		wxPD_CAN_ABORT		|
		wxPD_SMOOTH  // - makes indeterminate mode bar on WinXP very small
	);

	dialog.SetSize(wxSize(700, 180));
	dialog.CenterOnParent();

	wxString tempstring;
	if(!tempstring.IsEmpty()) tempstring.Clear();
	if(format==DecompressMode)
	{
		tempstring.Printf(L"Decompressing: %s", item.Game.GetFullName().c_str());
	}
	else
	{
		tempstring.Printf(L"Compressing: %s to %s", item.Game.GetFullName().c_str(), showformat.c_str());
	}

	bool CompressAborted = false;

	for(lsn = 0; lsn < src.GetBlockCount(); lsn++)
	{
		src.ReadBlock (cdbuff, lsn);
		dst.WriteBlock(cdbuff, lsn);
		if (!dialog.Update ((lsn * 10000) / src.GetBlockCount(), tempstring))
		{
			CompressAborted = true;
			wxString CompressAbortFile( PathNameFile + L".ini" );
			wxFileConfig CompressAbortIni( wxEmptyString, wxEmptyString, CompressAbortFile,
				wxEmptyString, wxCONFIG_USE_RELATIVE_PATH );

			CompressAbortIni.Create();
			IniSaver saver(CompressAbortIni);
			saver.Entry(L"lsn",			lsn			);
			saver.Entry(L"CompressMode",format		);
			saver.Entry(L"SourceFile",	SrcFileName	);
			saver.Entry(L"PathNameFile",PathNameFile);
			saver.Entry(L"DstFileName",	DstFileName	);
			saver.Entry(L"TmpFileName", TmpFileName	);
			uint RestoreCount = 1;
			saver.Entry(L"RestoreCount",RestoreCount);
			break;
		}
	}
	src.Close();
	dst.Close();

	dialog.Hide();

	if(!content.IsEmpty()) content.Clear();
	if(CompressAborted)
	{

#if 0
		content.Printf( L"%sompressing done with error! Delete compressed with error file?",format==DecompressMode ? L"Dec" : L"C" );
		if( Msgbox::YesNo( content, _("Compressing Error") ) )
		{
			wxRemoveFile( TmpFileName );            
			wxRemoveFile( TmpFileName + L".table" ); //remove table
			wxRemoveFile( PathNameFile + L".ini" );
		}
#endif
		RefreshSelections();
		m_listview->RefreshItems(0, m_listview->GetItemCount());
		return;
	}

	if(!wxRenameFile( TmpFileName, DstFileName )) 
	{
		Console.Error(L"Error rename %s to %s", TmpFileName.c_str(), DstFileName.c_str());
	}
	if(!wxRenameFile( TmpFileName + L".table", DstFileName + L".table" ))
	{
		 Console.Error(L"Error rename %s.table to %s.table", TmpFileName.c_str(), DstFileName.c_str());
	}
	if(format==DecompressMode)
	{
		content.Printf( _T( "Decompressing done. Delete compressed %s?"), item.GameName.c_str() );
	}
	else
	{
		content.Printf( _T("Compressing done. Delete original %s?"), item.Game.GetFullName().c_str() );
	}
	if( Msgbox::YesNo( content, (_T("%s"), format==DecompressMode?L"Decompressing done.":L"Compressing done.") ) )
	{
		m_listview->RefreshItems(0,m_listview->GetItemCount());

		// emulating click delete button
		wxCommandEvent refit( wxEVT_COMMAND_BUTTON_CLICKED );
		refit.SetId( DeleteGameButton->GetId() );
		GetEventHandler()->AddPendingEvent( refit );
		//
	}
	else
	{
		RefreshList();
		m_listview->RefreshItems(0, m_listview->GetItemCount());
	}
}

void Panels::GameSelectorPanel::Compress_Resume( wxCommandEvent& evt )
{
	int sel = m_listview->GetFirstSelected();
	GameListItem& item( m_Games[sel] );

	wxString content;

	u8 cdbuff[CD_FRAMESIZE_RAW];
	isoFile src, dst;

	u32 lsn					= -1;
	uint format				= -1;
	wxString DstFileName	= wxEmptyString;
	wxString SrcFileName	= wxEmptyString;
	wxString showformat		= wxEmptyString;

	wxFileName	DstFileNameF = Path::Combine(m_FolderPicker->GetPath().ToString(), item.Game.GetName()		);
	wxString	PathNameFile = Path::Combine(m_FolderPicker->GetPath().ToString(), DstFileNameF.GetName()	);
	wxString	TmpFileName  = Path::Combine(m_FolderPicker->GetPath().ToString(), item.Game.GetFullName()	);

	wxFileName IniFileNameF( PathNameFile + L".ini" );

	wxFile fp;
	if( !fp.Access(IniFileNameF.GetFullPath(), fp.read) )
	{
		Console.Error(L"Error: %s not found!", IniFileNameF.GetFullName().c_str());
		return;
	}

	wxString CompressAbortFile( IniFileNameF.GetFullPath() );
	wxFileConfig CompressAbortIni( wxEmptyString, wxEmptyString, CompressAbortFile,
		wxEmptyString, wxCONFIG_USE_RELATIVE_PATH );

	uint RestoreCount = -1;
	IniLoader loader(CompressAbortIni);
	loader.Entry(L"lsn",			lsn			);
	loader.Entry(L"CompressMode",	format		);
	loader.Entry(L"SourceFile",		SrcFileName	);
	loader.Entry(L"PathNameFile",	PathNameFile);
	loader.Entry(L"DstFileName",	DstFileName	);
	loader.Entry(L"TmpFileName",	TmpFileName	);
	loader.Entry(L"RestoreCount",	RestoreCount);
	

	wxFileName SrcFileNameF(SrcFileName);

	DevCon.WriteLn(L"SrcFileName  = %s",	SrcFileName	.c_str());
	DevCon.WriteLn(L"DstFileName  = %s",	DstFileName	.c_str());
	DevCon.WriteLn(L"TmpFileName  = %s",	TmpFileName.c_str());
	DevCon.WriteLn(L"IniFileName  = %s%s",	PathNameFile.c_str(), L".ini");
	DevCon.WriteLn(L"Format       = %d",	format);

	if( 
		lsn				== -1				||
		format			== -1				||
		DstFileName		== wxEmptyString	|| 
		SrcFileName		== wxEmptyString	||
		TmpFileName		== wxEmptyString
	  )
	{
		Console.Error(L"Error read from %s!", IniFileNameF.GetFullName().c_str());
		return;
	}

	if( format == Compress_to_Z2 )			showformat = L".Z2";
	else if( format == Compress_to_BZ2)		showformat = L".BZ2";
	else if( format == Compress_to_Z3 )     showformat = L".Z3";
	else if( format==DecompressMode ) {}
	else 
	{
		Console.Error(L"Unknown compress mode!");
		return;
	}

	src.Open( SrcFileName );

	if( format == Compress_to_Z2 )
		dst.Create(TmpFileName, ISOFLAGS_Z2, false);
	else if( format == Compress_to_BZ2 )
		dst.Create(TmpFileName, ISOFLAGS_BZ2, false);
	else if( format == Compress_to_Z3 )   
		dst.Create(TmpFileName, ISOFLAGS_Z3, false);
	else if( format==DecompressMode ) 
		dst.Create(TmpFileName, 0, false);
	else
	{
		Console.Error(L"COMPRESS ERROR: Unknown compress mode!");
		return;
	}

	dst.WriteFormat(src.GetBlockOffset(), src.GetBlockSize(), src.GetBlockCount());

	wxProgressDialog 
		dialog(
		(_T("%s"), format==DecompressMode ? L"Decompressing ISO" : L"Compressing ISO"),
		_T("Loading..."),
		10000, // range
		this, // parent
		wxPD_APP_MODAL		|
		wxPD_ELAPSED_TIME	|
		wxPD_ESTIMATED_TIME |
		wxPD_REMAINING_TIME |
		wxPD_CAN_SKIP		|
		wxPD_CAN_ABORT		|
		wxPD_SMOOTH  // - makes indeterminate mode bar on WinXP very small
	);

	dialog.SetSize(wxSize(700, 180));
	dialog.CenterOnParent();

	wxString tempstring;
	if(!tempstring.IsEmpty()) tempstring.Clear();
	if(format==DecompressMode)
	{
		tempstring.Printf(L"Decompressing: %s", SrcFileNameF.GetFullName().c_str());
	}
	else
	{
		tempstring.Printf(L"Compressing: %s to %s", SrcFileNameF.GetFullName().c_str(), showformat.c_str());
	}
	bool CompressAborted = false;

	for(u32 lsn2 = 0; lsn2 < src.GetBlockCount(); lsn2++)
	{
		src.ReadBlock (cdbuff, lsn2);
		dst.WriteBlock(cdbuff, lsn2);
		if (!dialog.Update (((lsn + lsn2) * 10000) / (src.GetBlockCount() + lsn), tempstring))
		{
			CompressAborted = true;
			CompressAbortIni.Create();
			IniSaver saver(CompressAbortIni);
			uint _lsn = lsn2+lsn;
			saver.Entry(L"lsn",			_lsn		);
			saver.Entry(L"CompressMode",format		);
			saver.Entry(L"SourceFile",	SrcFileName	);
			saver.Entry(L"PathNameFile",PathNameFile);
			saver.Entry(L"DstFileName",	DstFileName	);
			saver.Entry(L"TmpFileName", TmpFileName	);
			RestoreCount++;
			saver.Entry(L"RestoreCount",RestoreCount);
			break;
		}
	}

	src.Close();
	dst.Close();

	dialog.Hide();

	if(!content.IsEmpty()) content.Clear();
	if(CompressAborted)
	{
#if 0
		content.Printf( L"%sompressing done with error! Delete compressed with error file?", 
			format==DecompressMode ? L"Dec" : L"C");

		if( Msgbox::YesNo( content, _T("Compressing Error") ) )
		{
			wxRemoveFile( TmpFileName );            
			wxRemoveFile( TmpFileName + L".table" ); //remove table
			wxRemoveFile( PathNameFile + L".ini" );
		}
#endif
		RefreshSelections();
		m_listview->RefreshItems(0, m_listview->GetItemCount());
		return;
	}

	wxRemoveFile( PathNameFile + L".ini" );

	if(!wxRenameFile( TmpFileName, DstFileName )) 
	{
		Console.Error(L"Error rename %s to %s", TmpFileName.c_str(), DstFileName.c_str());
	}
	if(!wxRenameFile( TmpFileName + L".table", DstFileName + L".table" ))
	{
		 Console.Error(L"Error rename %s.table to %s.table", TmpFileName.c_str(), DstFileName.c_str());
	}
	if(format==DecompressMode)
	{
		content.Printf( _T( "Decompressing done. Delete compressed %s?"), item.GameName.c_str() );
	}
	else
	{
		content.Printf( _T("Compressing done. Delete original %s?"), SrcFileNameF.GetFullName().c_str() );
	}
	if( Msgbox::YesNo( content, (_T("%s"), format==DecompressMode?L"Decompressing done.":L"Compressing done.") ) )
	{
		m_listview->RefreshItems(0,m_listview->GetItemCount());

		// emulating click delete button
		wxCommandEvent refit( wxEVT_COMMAND_BUTTON_CLICKED );
		refit.SetId( DeleteGameButton->GetId() );
		GetEventHandler()->AddPendingEvent( refit );
		//
	}
	else
	{
		RefreshList();
		m_listview->RefreshItems(0, m_listview->GetItemCount());
	}
}

void Panels::GameSelectorPanel::Decompress	 ( wxCommandEvent& evt ){ Compress(DecompressMode  ); }
void Panels::GameSelectorPanel::Compress_Z   ( wxCommandEvent& evt ){ Compress(Compress_to_Z   ); }
void Panels::GameSelectorPanel::Compress_Z2  ( wxCommandEvent& evt ){ Compress(Compress_to_Z2  ); }
void Panels::GameSelectorPanel::Compress_BZ2 ( wxCommandEvent& evt ){ Compress(Compress_to_BZ2 ); }
void Panels::GameSelectorPanel::Compress_Z3  ( wxCommandEvent& evt ){ Compress(Compress_to_Z3); }

void Panels::GameSelectorPanel::ResumeGame   ( wxCommandEvent& evt ){ CoreThread.Resume	();	}
void Panels::GameSelectorPanel::PauseGame    ( wxCommandEvent& evt ){ CoreThread.Suspend();	}
void Panels::GameSelectorPanel::StopGame     ( wxCommandEvent& evt )
{
	g_Conf->EmuOptions.GameSelector.LastBootedGame = -1;
	DiskInfoReset();
	CoreThread.Reset();
	m_listview->RefreshItems(0, m_listview->GetItemCount());
}
void Panels::GameSelectorPanel::ResetGame    ( wxCommandEvent& evt ){ sApp.SysExecute(); }

Panels::GameSelectorPanel::~GameSelectorPanel() throw (){}

void Panels::GameSelectorPanel::OnOpenItemContextMenu(wxListEvent& evt)
{
	//int idx = evt.GetIndex();

	int sel = m_listview->GetFirstSelected();

	wxMenu* junk = new wxMenu();

	const GameListItem& item( m_Games[sel] );

	if(//(SysHasValidState() || CorePlugins.AreAnyInitialized())&& //Fixme.
		g_Conf->EmuOptions.GameSelector.LastBootedGame == sel && !item.CAborted)
	{
		if(CoreThread.IsClosing())junk->Append( GameMenuId_ResumeGame, _("Resume")  );
		else junk->Append( GameMenuId_PauseGame, _("Pause")  );
		junk->Append( GameMenuId_ResetGame, _("Reboot")  );
		junk->Append( GameMenuId_StopGame, _("Stop")  );
		junk->AppendSeparator();
	}
	else //if( idx != wxNOT_FOUND )
	{
		if(!item.CAborted)
		{
			junk->Append( GameMenuId_BootIso, _("Boot")  );
			junk->AppendSeparator();
		}

		if(item.TCompressed || item.UtCompressed)
		{
			junk->Append( GameMenuId_Decompress, _("Decompress") );
			junk->AppendSeparator();
		}
		else if(item.showtype != L"Illegal Disk" && item.showtype != L"Audio CD" && !item.BlockDump)
		{
			wxMenu* junk2 = new wxMenu();
			junk->AppendSubMenu(junk2,  _("Compress to") );
			//junk2->Append( GameMenuId_Compress_Z,		_(".Z" )   );
			junk2->Append( GameMenuId_Compress_Z2,		_(".Z2")   );
			//junk2->Append( GameMenuId_Compress_Z3,	_(".Z3")  );
			junk2->Append( GameMenuId_Compress_BZ2,		_(".BZ2")   );

			wxMenuItem* Z2CompressItem = junk2->FindItem( GameMenuId_Compress_Z2 );
			wxMenuItem* BZ2CompressItem = junk2->FindItem( GameMenuId_Compress_BZ2 );
			Z2CompressItem->Enable(g_Conf->EmuOptions.GameSelector.LastBootedGame == -1);
			BZ2CompressItem->Enable(g_Conf->EmuOptions.GameSelector.LastBootedGame == -1);

			junk->AppendSeparator();
		}
		else if(item.CAborted)
		{
			junk->Append( GameMenuId_Resume_Compress,  _("Resume compress") );
			junk->AppendSeparator();
		}

		if(!item.CAborted)
		{
			junk->Append( GameMenuId_SetSettingsGame,  _("Set Settings...") );
		}

		junk->Append( GameMenuId_RenameGame,  _("Rename") );
		junk->Append( GameMenuId_Delete,      _("Delete") );

		wxMenuItem* DeleteGameItem = junk->FindItem( GameMenuId_Delete );
		DeleteGameItem->Enable(g_Conf->EmuOptions.GameSelector.LastBootedGame == -1);

		junk->AppendSeparator();

		//junk->AppendCheckItem(GameMenuId_SkipBIOS,	_("Enable Skip BIOS"));
		//junk->Check( GameMenuId_SkipBIOS, g_Conf->EmuOptions.GameSelector.enableSkipBIOS );

		//junk->AppendSeparator();
	}

	junk->Append( GameMenuId_RefreshList, _("Refresh List") );
	
	PopupMenu( junk );
	m_listview->RefreshItem( sel );
	UpdateBootons();
}

void Panels::GameSelectorPanel::Apply()
{
	SaveColSize();
#ifdef USEBLOCKDUMPING
	g_Conf->EmuOptions.GameSelector.enableDumpBlocks = m_BlockDumping    ->GetValue();
#else
	g_Conf->EmuOptions.GameSelector.enableDumpBlocks = false;
#endif
	g_Conf->EmuOptions.GameSelector.enableSkipBIOS   = m_ENABLEskipBIOS  ->GetValue();
}

void Panels::GameSelectorPanel::AppStatusEvent_OnSettingsApplied()
{
	m_ENABLEskipBIOS	->SetValue(g_Conf->EmuOptions.GameSelector.enableSkipBIOS);
#ifdef USEBLOCKDUMPING
	m_BlockDumping  	->SetValue(g_Conf->EmuOptions.GameSelector.enableDumpBlocks);
#endif
}

bool Panels::GameSelectorPanel::ValidateEnumerationStatus()
{
	if( m_listview ) m_listview->SetGameProvider( NULL );

	bool validated = true;

	ScopedPtr<wxArrayString> gameslist( new wxArrayString() );
	ScopedPtr<wxArrayString> CAgameslist( new wxArrayString() );

	if( m_FolderPicker->GetPath().Exists() )
	{
		wxDir::GetAllFiles( m_FolderPicker->GetPath().ToString(), gameslist, L"*.iso",  wxDIR_FILES );
		wxDir::GetAllFiles( m_FolderPicker->GetPath().ToString(), gameslist, L"*.mdf",  wxDIR_FILES );
		wxDir::GetAllFiles( m_FolderPicker->GetPath().ToString(), gameslist, L"*.nrg",  wxDIR_FILES );
		wxDir::GetAllFiles( m_FolderPicker->GetPath().ToString(), gameslist, L"*.bin",  wxDIR_FILES );
		wxDir::GetAllFiles( m_FolderPicker->GetPath().ToString(), gameslist, L"*.img",  wxDIR_FILES );
		wxDir::GetAllFiles( m_FolderPicker->GetPath().ToString(), gameslist, L"*.dump", wxDIR_FILES );

		wxDir::GetAllFiles( m_FolderPicker->GetPath().ToString(), gameslist, L"*.Z",    wxDIR_FILES );
		wxDir::GetAllFiles( m_FolderPicker->GetPath().ToString(), gameslist, L"*.Z2",   wxDIR_FILES );
		wxDir::GetAllFiles( m_FolderPicker->GetPath().ToString(), gameslist, L"*.BZ2",  wxDIR_FILES );
		wxDir::GetAllFiles( m_FolderPicker->GetPath().ToString(), gameslist, L"*.Z3",   wxDIR_FILES );

		wxDir::GetAllFiles( m_FolderPicker->GetPath().ToString(), CAgameslist, L"*.tmp", wxDIR_FILES );
	}

	if( ( !m_GamesList         || (*gameslist   != *m_GamesList         )) ||
		( !m_CAbortedGamesList || (*CAgameslist != *m_CAbortedGamesList )) 
	  ) validated = false;

	m_CAbortedGamesList.SwapPtr( CAgameslist );
	m_GamesList.SwapPtr( gameslist );
	return validated;
}

void Panels::GameSelectorPanel::DoRefresh()
{
	if( !m_GamesList ) return;
	if( m_GamesList->GetCount() == 0 ) return;

	static int countboot = 0;
	countboot++;
	if(countboot >= 2)
	{
		countboot = 0; //For reopen manager...
	}
	else
	{
		RefreshList();
		return;
	}

	if( m_Games.GetPtr() != NULL ) m_Games.Delete();

	m_Games	= new GameListItem[m_GamesList->GetCount() + m_CAbortedGamesList->GetCount()];

	g_Conf->EmuOptions.GameSelector.enableShowLogCDVD = false;
	m_listview->Refresh();

	bool dumpback = false;
#ifdef USEBLOCKDUMPING
	if(g_Conf->EmuOptions.CdvdDumpBlocks)
	{
		g_Conf->EmuOptions.CdvdDumpBlocks = false;
		dumpback = true;
	}
#endif

// --------------------------------------------------------------------------
// ProgressDialog
// --------------------------------------------------------------------------
	wxProgressDialog 
		dialog(
		_T("Loading ISOs"),
		_T("Loading..."),
		(int)m_GamesList->GetCount() + m_CAbortedGamesList->GetCount(), // range
		this, // parent
		wxPD_APP_MODAL |
		wxPD_ELAPSED_TIME |
		wxPD_ESTIMATED_TIME |
		wxPD_REMAINING_TIME |
		wxPD_SMOOTH // - makes indeterminate mode bar on WinXP very small
	);

	dialog.SetSize(wxSize(340, 180));
	dialog.CenterOnParent();
// --------------------------------------------------------------------------

	for( size_t i=0; i<m_GamesList->GetCount(); ++i )
	{
		wxString GameName((*m_GamesList)[i]);
		wxFileName Game( g_Conf->Folders.Games + GameName );

		//m_listview->SetItemColumnImage((int)i, 8, res_Flag_Europe::Data);
		//m_listview->SetColumnImage(8, res_Flag_Europe::Data);

// --------------------------------------------------------------------------
// UpdateProgressDialog
// --------------------------------------------------------------------------
		wxString tempstring;
		if(!tempstring.IsEmpty()) tempstring.Clear();
		tempstring.Printf(L"Loading: %s", Game.GetFullName().c_str());

		// Update with the progress (i) and the message (msg)
		if (!dialog.Update(i, tempstring)) break;
// --------------------------------------------------------------------------

		if( !UpdateGameInfo( m_Games[i], (*m_GamesList)[i]) ) continue;
		UpdateItemCol( m_Games[i] );
		//m_Games[i].Count = i;
	}

	for( size_t i=0; i<m_CAbortedGamesList->GetCount(); ++i )
	{
		wxString GameName((*m_CAbortedGamesList)[i]);
		wxFileName Game( g_Conf->Folders.Games + GameName );

		wxString tempstring;
		if(!tempstring.IsEmpty()) tempstring.Clear();
		tempstring.Printf(L"Loading: %s", Game.GetFullName().c_str());

		if (!dialog.Update(i + m_GamesList->GetCount(), tempstring)) break;

		ACUpdateGameInfo( m_Games[i + m_GamesList->GetCount()], (*m_CAbortedGamesList)[i]);
		UpdateItemCol( m_Games[i + m_GamesList->GetCount()] );
	}
	
	if( m_listview ) m_listview->SetGameProvider( this );

	g_GameStarted = false;
	g_SkipBiosHack = EmuConfig.UseBOOT2Injection;

	DiskInfoReset();

	g_Conf->EmuOptions.GameSelector.enableShowLogCDVD = true;
	g_Conf->EmuOptions.CdvdDumpBlocks = dumpback;
}

void Panels::GameSelectorPanel::RefreshList() const
{
	m_listview->RefreshItems(0, m_listview->GetItemCount());

	wxCommandEvent refit( wxEVT_COMMAND_BUTTON_CLICKED );
	refit.SetId( refreshButton->GetId() );
	GetEventHandler()->AddPendingEvent( refit );
}

void Panels::GameSelectorPanel::BootGameIsoDClick( wxListEvent& evt )
{
	m_listview->RefreshItems(0, m_listview->GetItemCount());

	wxCommandEvent refit( wxEVT_COMMAND_MENU_SELECTED );
	refit.SetId( GameMenuId_BootIso );
	GetEventHandler()->AddPendingEvent( refit );
}

void Panels::GameSelectorPanel::UpdateBootons(wxListEvent& evt)
{
	if( !m_listview ) return;
	
	int sel = m_listview->GetFirstSelected();

	m_listview->RefreshItem(sel);

	if( wxNOT_FOUND == sel 
		|| g_Conf->EmuOptions.GameSelector.LastBootedGame != -1 
		|| g_Conf->EmuOptions.GameSelector.LastBootedGame == sel )
	{
		DeleteGameButton->Disable();
	}
	else DeleteGameButton->Enable();
}

void Panels::GameSelectorPanel::UpdateBootons()
{
	if( !m_listview ) return;
	
	int sel = m_listview->GetFirstSelected();

	m_listview->RefreshItem(sel);

	if( wxNOT_FOUND == sel 
		|| g_Conf->EmuOptions.GameSelector.LastBootedGame != -1 
		|| g_Conf->EmuOptions.GameSelector.LastBootedGame == sel )
	{
		DeleteGameButton->Disable();
	}
	else DeleteGameButton->Enable();
}

void Panels::GameSelectorPanel::OnRenameGame ( wxCommandEvent& evt )
{
	int sel = m_listview->GetFirstSelected();
	GameListItem& item(m_Games[sel]);
	wxWindowID result = Dialogs::RenameGame( this, item.Game.GetFullPath(), item.TCompressed ).ShowModal();
	if(result == wxID_OK)
	{
		RefreshList();
	}
}

void Panels::GameSelectorPanel::OnDeleteGame(wxCommandEvent& evt)
{
	ScopedCoreThreadClose closed_core;

	int sel = m_listview->GetFirstSelected();
	GameListItem& item(m_Games[sel]);

	wxString content;
	
	if( item.TCompressed ) 
	{
		content.Printf( _T("You sure delete %s and %s.table?"), 
			item.Game.GetFullName().c_str(), 
			item.Game.GetFullName().c_str() );
		
		if( Msgbox::YesNo(content, _("Delete Game")) )
		{
			wxRemoveFile( item.Game.GetFullPath() );            
			wxRemoveFile( item.Game.GetFullPath() + L".table" );

			RefreshSelections();
			m_listview->RefreshItems(0, m_listview->GetItemCount());
		}
	}
	else if( item.CAborted ) 
	{
		wxFileName NameTmp(Path::Combine(m_FolderPicker->GetPath().ToString(), item.Game.GetName()));
		wxString Name(NameTmp.GetName());
		content.Printf( _T("You sure delete %s, %s.table and %s.ini?"), 
			item.Game.GetFullName().c_str(), 
			item.Game.GetFullName().c_str(), Name.c_str() );
		
		if( Msgbox::YesNo(content, _("Delete Game")) )
		{
			wxRemoveFile( item.Game.GetFullPath() );            
			wxRemoveFile( item.Game.GetFullPath() + L".table" );
			wxRemoveFile( Path::Combine(m_FolderPicker->GetPath().ToString(), Name + L".ini"));

			RefreshSelections();
			m_listview->RefreshItems(0, m_listview->GetItemCount());
		}
	}
	else 
	{
		content.Printf( _T("You sure delete %s?"), item.Game.GetFullName().c_str() );

		if( Msgbox::YesNo(content, _("Delete Game")) )
		{
			wxRemoveFile( item.Game.GetFullPath() );

			RefreshSelections();
			m_listview->RefreshItems(0, m_listview->GetItemCount());
		}
	}

	closed_core.AllowResume();
}

int Panels::GameSelectorPanel::GetLength() const
{
	return m_GamesList->GetCount() + m_CAbortedGamesList->GetCount();
}

void Panels::GameSelectorPanel::ACUpdateGameInfo( GameListItem& item, const wxString& filename)
{
	item.Game = g_Conf->Folders.Games + filename;
	wxFile fp;
	
	if( fp.Access(
			Path::Combine(
			g_Conf->Folders.Games, 
			wxFileName(Path::Combine(g_Conf->Folders.Games, item.Game.GetName())).GetName()+L".ini")
			, fp.read
		) 
	)
	{
		item.CAborted = true;
	}

	item.GameName = item.Game.GetName();

	item.Game.GetTimes( NULL, &item.DateModified, &item.DateCreated );

	if( !item.Game.FileExists() ) return;

	fp.Open( item.Game.GetFullPath() );
	if( !fp.IsOpened() ) return;

	if((float)fp.Length()/(1024*1024) >= 1000.00)
	{
		item.gamesize = L"GB";
		item.gameFileSizeMB = fp.Length()/(1024*1024);
	}
	else
	{
		item.gamesize = L"MB";
		item.gameFileSizeMB = fp.Length() / 1024;
	}

	fp.Close();
}

bool Panels::GameSelectorPanel::UpdateGameInfo( GameListItem& item, const wxString& filename)
{
	item.Game = g_Conf->Folders.Games + filename;

	if( !item.Game.FileExists() ) return false;

	wxFile fp( item.Game.GetFullPath() );
	if( !fp.IsOpened() ) return FALSE;

	if((float)fp.Length()/(1024*1024) >= 1000.00)
	{
		item.gamesize = L"GB";
		item.gameFileSizeMB = fp.Length()/(1024*1024);
	}
	else
	{
		item.gamesize = L"MB";
		item.gameFileSizeMB = fp.Length() / 1024;
	}

	fp.Close();
	
	item.Game.GetTimes( NULL, &item.DateModified, &item.DateCreated );

	isoFile iso;
	iso.Open(item.Game.GetFullPath());

	if (iso.Detect())
	{
		item.BlockDump		= iso.IsDump();

		if(iso.IsTCompressed())
		{
			item.TCompressed = true;
		}
		else if(iso.IsUtCompressed())
		{
			item.UtCompressed = true;
		}
	}
	else
	{
		Console.Error(L"Error detect %s", item.Game.GetFullName().c_str());
		iso.Close();
		return false;
	}

	switch(iso.GetType())
	{
		case ISOTYPE_CD:            	item.showtype = L"CD";      		  break;
        case ISOTYPE_DVD:           	item.showtype = L"DVD";     		  break;
        case ISOTYPE_AUDIO:         	item.showtype = L"Audio CD";          break;
        case ISOTYPE_DVDDL:         	item.showtype = L"DVD9 (dual-layer)"; break;
		case ISOTYPE_ILLEGAL:default:   item.showtype = L"Illegal Disk";      break;
	}
	iso.Close();

	if(item.showtype != L"Illegal Disk" && item.showtype != L"Audio CD")
	{
		CDVDsys_ChangeSource( CDVDsrc_Iso );

		CDVD->open( item.Game.GetFullPath().ToUTF8() );

		wxString elfpath;
		u32 discType = GetPS2ElfName(elfpath);
		switch(discType)
		{
		case 0: item.showdisctype = L"Unknown"; break;
		case 1: item.showdisctype = L"PS1";     break;
		case 2: item.showdisctype = L"PS2";     break;
		}

		cdvdReloadElfInfo(elfpath);

		if(IGameDatabase* GameDB = AppHost_GetGameDatabase())
		{
			const wxString GameKey( SysGetDiscID() );
			Game_Data game;
			if (GameDB->findGame(game, GameKey))
			{
				//int compat = game.getInt("Compat");
				item.GameName = game.getString("Name");
				item.Region  = game.getString("Region");
				//item.Compat = L" [Status = "+compatToStringWX(compat)+L"]";
			}
		}

		if( item.GameName.IsEmpty() )
		{
			item.GameName = item.Game.GetName();
		}

		item.DiskName = item.Game.GetName();

		if( item.Region.IsEmpty() )
		{
			item.Region = g_Conf->EmuOptions.GameSelector.CurVMODE;
		}

		if(!DiscSerial.IsEmpty()) item.Serial = DiscSerial;
		item.crc = ElfCRC;

		DoCDVDclose();
	}
	
	return true;
}

void Panels::GameSelectorPanel::UpdateItemCol( GameListItem& it )
{
	bool showed[GameCol_Count];
	for(int i = 0; i < GameCol_Count; i++) showed[i] = false;


	for(int c = 0; c < GameCol_Count; ++c)
	{
		if((ShowCol[GameCol_Filename]) && (!showed[GameCol_Filename]) && (c <= GameCol_Filename))
		{
			showed[GameCol_Filename] = true;
			it.s[c] = ShowCol[GameCol_IsoFormat] ? it.GameName : it.DiskName + L"." + it.Game.GetExt();
		}
		else if((ShowCol[GameCol_Size]) && (!showed[GameCol_Size]) && (c <= GameCol_Size))
		{
			showed[GameCol_Size] = true;
			it.s[c] = wxsFormat( L"%.02f ", it.gameFileSizeMB/1024) + it.gamesize;
		}
		else if((ShowCol[GameCol_TypeDisk]) && (!showed[GameCol_TypeDisk]) && (c <= GameCol_TypeDisk))
		{
			showed[GameCol_TypeDisk] = true;
			it.s[c] = it.showtype;
		}
		else if((ShowCol[GameCol_TypeGame]) && (!showed[GameCol_TypeGame]) && (c <= GameCol_TypeGame))
		{
			showed[GameCol_TypeGame] = true;
			it.s[c] = it.showdisctype;
		}
		else if((ShowCol[GameCol_CRC]) && (!showed[GameCol_CRC]) && (c <= GameCol_CRC))
		{
			showed[GameCol_CRC] = true;
			it.s[c] = it.crc ? wxsFormat( L"0x%08X", it.crc ) : wxsFormat( L"Unknown" );
		}
		else if((ShowCol[GameCol_Serial]) && (!showed[GameCol_Serial]) && (c <= GameCol_Serial))
		{
			showed[GameCol_Serial] = true;
			it.s[c] = it.Serial;
		}
		else if((ShowCol[GameCol_Region]) && (!showed[GameCol_Region]) && (c <= GameCol_Region))
		{
			showed[GameCol_Region] = true;
			it.s[c] = it.Region.IsEmpty() ? wxsFormat( L"Unknown" ) : it.Region;
		}
		else if((ShowCol[GameCol_IsoFormat]) && (!showed[GameCol_IsoFormat]) && (c <= GameCol_IsoFormat))
		{
			showed[GameCol_IsoFormat] = true;
			it.s[c] = it.Game.GetExt();
		}
		else if((ShowCol[GameCol_DateModified]) && (!showed[GameCol_DateModified]) && (c <= GameCol_DateModified))
		{
			showed[GameCol_DateModified] = true;
			it.s[c] = it.DateModified.FormatDate();
		}
		else if((ShowCol[GameCol_DateCreated]) && (!showed[GameCol_DateCreated]) && (c <= GameCol_DateCreated))
		{
			showed[GameCol_DateCreated] = true;
			it.s[c] = it.DateCreated.FormatDate();
		}
	}
}


// =====================================================================================================
//  BootGame (CDVD/ISO)
// =====================================================================================================
void Panels::GameSelectorPanel::BootGameCDVD( wxCommandEvent& evt )
{
	Apply();

	g_Conf->EmuOptions.GameSelector.LastBootedGame = -1;
	m_listview->RefreshItems(0,m_listview->GetItemCount());
	UpdateBootons();

	if(!CoreThread.IsClosing()&& CorePlugins.AreAnyInitialized())CoreThread.Suspend(); //HACK!
	if( SysHasValidState() )
	{
		DoCDVDclose();
		CoreThread.Reset();

		wxCommandEvent refit( wxEVT_COMMAND_BUTTON_CLICKED );
		refit.SetId( BootCDVDButton->GetId() );
		GetEventHandler()->AddPendingEvent( refit );
	}
	else
	{
		// ---------------------------------------------------
		// Skip BIOS
		// ---------------------------------------------------
		if( g_Conf->EmuOptions.GameSelector.enableSkipBIOS )
			g_Conf->EmuOptions.UseBOOT2Injection = true;
		else
			g_Conf->EmuOptions.UseBOOT2Injection = false;
		// ---------------------------------------------------
		// Dump Blocks
		// ---------------------------------------------------
		if(g_Conf->EmuOptions.GameSelector.enableDumpBlocks)
			g_Conf->EmuOptions.CdvdDumpBlocks = true;
		else
			g_Conf->EmuOptions.CdvdDumpBlocks = false;
		// ---------------------------------------------------

		g_Conf->CdvdSource = CDVDsrc_Plugin;
		CDVDsys_ChangeSource( CDVDsrc_Plugin );
		sApp.SysExecute( CDVDsrc_Plugin );
	}
}

void Panels::GameSelectorPanel::BootGameIso( wxCommandEvent& evt )
{	
	Apply();

	const int cbGame = m_listview->GetFirstSelected();

	const GameListItem& item( m_Games[cbGame] );

	if(item.CAborted) return;

	if(!CoreThread.IsClosing() && CorePlugins.AreAnyInitialized())CoreThread.Suspend(); //HACK!
	if( SysHasValidState() && cbGame != g_Conf->EmuOptions.GameSelector.LastBootedGame )   //close
	{
		DoCDVDclose();
		CoreThread.Reset();

		wxCommandEvent refit( wxEVT_COMMAND_MENU_SELECTED );
		refit.SetId( GameMenuId_BootIso );
		GetEventHandler()->AddPendingEvent( refit );
	}
	else if(cbGame == g_Conf->EmuOptions.GameSelector.LastBootedGame 
		&& SysHasValidState()&& CoreThread.IsClosing())                                    //resume
	{
		CoreThread.Resume();
	}
	else if(cbGame == g_Conf->EmuOptions.GameSelector.LastBootedGame &&                    //reboot
		SysHasValidState() && !CoreThread.IsClosing())
	{
		sApp.SysExecute();
	}
	else
	{
		g_Conf->EmuOptions.GameSelector.LastBootedGame = cbGame;
		m_listview->RefreshItems(0,m_listview->GetItemCount());
		UpdateBootons();
		
		// ---------------------------------------------------
		// Skip BIOS
		// ---------------------------------------------------
		if( g_Conf->EmuOptions.GameSelector.enableSkipBIOS )
			g_Conf->EmuOptions.UseBOOT2Injection = true;
		else
			g_Conf->EmuOptions.UseBOOT2Injection = false;
		// ---------------------------------------------------
		// Dump Blocks
		// ---------------------------------------------------
		if(g_Conf->EmuOptions.GameSelector.enableDumpBlocks && !item.BlockDump)
			g_Conf->EmuOptions.CdvdDumpBlocks = true;
		else
			g_Conf->EmuOptions.CdvdDumpBlocks = false;
		// ---------------------------------------------------

		g_Conf->CdvdSource = CDVDsrc_Iso;
		CDVDsys_ChangeSource( CDVDsrc_Iso );
		g_Conf->CurrentIso = item.Game.GetFullPath();
		sApp.SysExecute( CDVDsrc_Iso );
	}
}

// =====================================================================================================
//  GameColumns
// =====================================================================================================

const GameListItem& Panels::GameSelectorPanel::GetGame( int idx ) const
{
	return m_Games[idx];
}

GameListItem& Panels::GameSelectorPanel::GetGame( int idx )
{
	return m_Games[idx];
}

GameSelectorPanel_List::GameSelectorPanel_List( wxWindow* parent )
	: _parent( parent )
{	
	//CreateColumns();
}

void GameSelectorPanel_List::CreateColumns()
{
	/*
	for( int i=0; i<GameCol_Count; ++i )
	{
		const GameListViewColumnInfo& info = GetDefaultColumnInfo(i);
		InsertColumn( i, pxGetTranslation(info.name), info.align, info.width );
	}
	*/
}

const GameListViewColumnInfo& GameSelectorPanel_List::GetDefaultColumnInfo( uint idx ) const
{
	static const GameListViewColumnInfo columns[] =
	{
		{ _("Filename"), 200,	wxLIST_FORMAT_LEFT   },
		{ _("Size"),      80,	wxLIST_FORMAT_RIGHT  },
		{ _("Disk type"), 80,	wxLIST_FORMAT_CENTER },
		{ _("Game type"), 80,	wxLIST_FORMAT_CENTER },
		{ _("CRC"),       80,  	wxLIST_FORMAT_CENTER },
		{ _("Serial"),    80,  	wxLIST_FORMAT_CENTER },
		{ _("Region"),    55,  	wxLIST_FORMAT_CENTER },
		{ _("Format"),    55,  	wxLIST_FORMAT_CENTER },
		{ _("Modified"),  96, 	wxLIST_FORMAT_LEFT   },
		{ _("Created" ),  96,  	wxLIST_FORMAT_LEFT   },
	};

	pxAssumeDev( idx < ArraySize(columns), "ListView column index is out of bounds." );
	return columns[idx];
}

void GameSelectorPanel_List::SetGameCount( int length )
{
	if( !m_GameProvider ) length = 0;
	SetItemCount( length );
	Refresh();
}

wxString GameSelectorPanel_List::OnGetItemText(long item, long column) const
{
	if( !m_GameProvider ) return _parent::OnGetItemText(item, column);

	const GameListItem& it( m_GameProvider->GetGame(item) );

	if(column > GameCol_Count)
	{
		pxFail( "Unknown column index in GameSelectorPanel_List -- returning an empty string." );
		return wxEmptyString;
	}

	return it.s[column];
}

void GameSelectorPanel_List::LoadSaveColumns( IniInterface& ini )
{
	FastFormatUnicode label;
	uint colcnt = GetColumnCount();
	for( uint col=0; col<colcnt; ++col )
	{
		const GameListViewColumnInfo& cinfo = GetDefaultColumnInfo(col);
		label.Clear();
		label.Write( L"ColumnWidth_%s", cinfo.name );
		int width = GetColumnWidth(col);
		ini.Entry( label, width, cinfo.width );
		
		if (ini.IsLoading())
			SetColumnWidth(col, width);
	}
}

int GameSelectorPanel_List::OnGetItemImage(long item) const
{
	return _parent::OnGetItemImage( item );
}

// return the icon for the given item and column.
int GameSelectorPanel_List::OnGetItemColumnImage(long item, long column) const
{
	return _parent::OnGetItemColumnImage( item, column );
}

static wxListItemAttr m_ItemAttr;

// return the attribute for the item (may return NULL if none)
wxListItemAttr* GameSelectorPanel_List::OnGetItemAttr(long item) const
{
	if( !m_GameProvider ) return _parent::OnGetItemAttr(item);
	const GameListItem& it( m_GameProvider->GetGame(item) );

	m_ItemAttr = wxListItemAttr();		// Wipe it clean!
	if(it.CAborted)
		m_ItemAttr.SetBackgroundColour( wxColour(L"Blue") );
	else if( g_Conf->EmuOptions.GameSelector.LastBootedGame == item )
		m_ItemAttr.SetBackgroundColour( wxColour(L"Wheat") );
	else if(it.showtype == L"Audio CD" || it.showtype == L"Illegal Disk")
		m_ItemAttr.SetBackgroundColour( wxColour(L"Orange") );
	else if(it.BlockDump)
		m_ItemAttr.SetBackgroundColour( wxColour(L"Blue") );
	else if(it.TCompressed || it.UtCompressed)
		m_ItemAttr.SetBackgroundColour( wxColour(L"Green") );

	return &m_ItemAttr;
}